﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Goods.Entity;
using NewRetail.Application.Components.Platform;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.PrintTask.Entity;
using NewRetail.Application.Components.PrintTask.Model;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Core.Entity;
using NewRetail.Application.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace NewRetail.Application.Components.PrintTask
{
    #region 接口
    /// <summary>
    /// 接口
    /// </summary>
    public interface IPrintTaskService : IApplicationService
    {
        #region 打印任务相关

        /// <summary>
        /// 保存条码打印任务
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<(int, string)> SavePrintTaskItems(PrintTaskSaveInputDto inputDto);


        Task<PrintTaskDataResultDto[]> AttachGoodsInfo(PrintTaskEntity[] data, string warehouseId);
        /// <summary>
        /// 更新打印状态
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<(string, string)> UpdatePrintTagByReceiptNo(ReceiptNoDto data);

        #endregion
    }
    #endregion

    #region 实现
    /// <summary>
    /// 实现
    /// </summary>
    public class PrintTaskService : ApplicationService, IPrintTaskService
    {
        #region Field
        private readonly ILogger _logger;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        protected IEntityHelper _entityHelper => this.LazyServiceProvider.LazyGetRequiredService<IEntityHelper>();
        protected INoGeneratorService _noGeneratorService => this.LazyServiceProvider.LazyGetRequiredService<INoGeneratorService>();
        private readonly IRepository<PrintTaskEntity> _printTaskRepository;
        private readonly IMapper _mapper;
        #endregion

        #region Constructor
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="printTaskRepository"></param>
        /// <param name="mapper"></param>
        /// <param name="unitOfWorkManager"></param>
        /// <param name="logger"></param>
        public PrintTaskService(IRepository<PrintTaskEntity> printTaskRepository, IMapper mapper, IUnitOfWorkManager unitOfWorkManager,
            ILogger<PrintTaskService> logger)
        {
            _printTaskRepository = printTaskRepository;
            _mapper = mapper;
            _unitOfWorkManager = unitOfWorkManager;
            _logger = logger;
        }
        #endregion

        #region method        

        #region 保存条码打印任务
        /// <summary>
        /// 保存条码打印任务
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<(int, string)> SavePrintTaskItems(PrintTaskSaveInputDto inputDto)
        {
            var result = 0;
            var errMsg = "";
            var receiptDate = inputDto.receiptDate;
            var receiptNo = inputDto.receiptNo;
            //根据单据号先获取打印任务
            var db = await _printTaskRepository.GetDbContextAsync();
            var printTask = await db.Set<PrintTaskEntity>().AsNoTracking().FirstOrDefaultAsync(x => x.receiptNo == receiptNo && x.printTag == 0);
            //如果不存在就新增
            if (printTask == null)
            {
                printTask = new PrintTaskEntity()
                {
                    receiptDate = receiptDate,
                    receiptNo = receiptNo,
                    printTag = inputDto.printTag,
                    printNo = inputDto.printNo
                };
                _entityHelper.InitEntity(printTask);
                await _printTaskRepository.InsertAsync(printTask, autoSave: true);
                result = 1;
            }
            else
                errMsg = "此单据打印任务已经存在";

            return (result, errMsg);
        }
        #endregion

        #region 附加商品信息
        /// <summary>
        /// 附加商品信息
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<PrintTaskDataResultDto[]> AttachGoodsInfo(PrintTaskEntity[] data, string warehouseId)
        {
            var todayDate = DateTime.Now;
            var objRet = _mapper.Map<IEnumerable<PrintTaskDataResultDto>>(data);
            var receiptNos = objRet.Select(x => x.receiptNo).ToList();
            var db = await _printTaskRepository.GetDbContextAsync();
            //采购
            var inOutWarehousingData = await db.Set<InOutWarehousing>().AsNoTracking().Where(x => receiptNos.Contains(x.receiptNo)).ToArrayAsync();
            //调价
            var goodsAdjustPricesData = await db.Set<GoodsAdjustPrice>().AsNoTracking().Where(x => receiptNos.Contains(x.receiptNo)).ToArrayAsync();
            //其他单
            var otherBillsData = await db.Set<OtherBill>().AsNoTracking().Where(x => receiptNos.Contains(x.receiptNo)).ToArrayAsync();

            await db.AttachData<GoodsInfo, InOutWarehousing>(inOutWarehousingData, x => x.goodsID, (m, arr) =>
            {
                m.GoodsInfo = arr.FirstOrDefault();
            });
            await db.AttachData<GoodsInfo, GoodsAdjustPrice>(goodsAdjustPricesData, x => x.goodsID, (m, arr) =>
            {
                m.GoodsInfo = arr.FirstOrDefault();
            });
            await db.AttachData<GoodsInfo, OtherBill>(otherBillsData, x => x.goodsID, (m, arr) =>
            {
                m.GoodsInfo = arr.FirstOrDefault();
            });
            //获取商品Id列表后，从warehousegoods表获取价格
            //采购产品
            var inOutWarehousingGoodsIds = inOutWarehousingData.Select(x => x.goodsID).Distinct();
            //调价产品
            var goodsAdjustPriceGoodsIds = goodsAdjustPricesData.Select(x => x.goodsID).Distinct();
            //其他单产品
            var otherBillsGoodsIds = otherBillsData.Select(x => x.goodsID).Distinct();
            //var goodIds = inOutWarehousingData.Select(x => x.goodsID).Distinct();
            //合并商品
            var goodsIds = inOutWarehousingGoodsIds.Union(goodsAdjustPriceGoodsIds).Union(otherBillsGoodsIds).Distinct();
            //获取仓库商品关联表信息
            var warehouseGoodsData = await db.Set<WarehouseGoods>().AsNoTracking().Where(x => x.warehouseID == warehouseId && goodsIds != null && goodsIds.Contains(x.goodsID)).ToArrayAsync();

            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year == todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();

            foreach (var item in objRet)
            {
                if (item.receiptNo.Substring(0, 2) == "IO")
                {
                    //采购
                    //item.quantity = inOutWarehousingData.FirstOrDefault(x => x.receiptNo == item.receiptNo).quantity;
                    var inOutGoodsInfos = inOutWarehousingData.Where(x => x.receiptNo == item.receiptNo).ToList().Select(x => x.GoodsInfo)?.ToArray();
                    if (inOutGoodsInfos != null && inOutGoodsInfos.Length > 0)
                        item.GoodsInfos = inOutGoodsInfos;// inOutWarehousingData.Where(x => x.receiptNo == item.receiptNo).ToList().Select(x => x.GoodsInfo).ToArray();
                    foreach (var goods in item.GoodsInfos)//item.GoodsInfos)
                    {
                        goods.qualityTime = Convert.ToInt32(inOutWarehousingData.FirstOrDefault(x => x.receiptNo == item.receiptNo && x.goodsID == goods.Id).quantity);
                        var price = warehouseGoodsData.Where(x => x.goodsID == goods.Id).FirstOrDefault()?.price;
                        var resultPrice = (price == null || price == 0) ? inOutWarehousingData.FirstOrDefault(x => x.receiptNo == item.receiptNo && x.goodsID == goods.Id).curSalePrice : price;
                        goods.price = (decimal)resultPrice;//(price == null || price == 0) ? inOutWarehousingData.FirstOrDefault(x => x.receiptNo == item.receiptNo && x.goodsID == goods.Id).curSalePrice : price;
                    }
                }
                else if (item.receiptNo.Substring(0, 2) == "TJ")
                {
                    //调价
                    var adjustGoodsInfos = goodsAdjustPricesData.Where(x => x.receiptNo == item.receiptNo).ToList().Select(x => x.GoodsInfo)?.ToArray();
                    if (adjustGoodsInfos != null && adjustGoodsInfos.Length > 0)
                        item.GoodsInfos = adjustGoodsInfos;//goodsAdjustPricesData.Where(x => x.receiptNo == item.receiptNo).ToList().Select(x => x.GoodsInfo).ToArray();
                    item.warehouseId = goodsAdjustPricesData.Where(x => x.receiptNo == item.receiptNo)?.FirstOrDefault()?.warehouseID;
                    foreach (var goodsAdjustPrice in item.GoodsInfos)//item.GoodsInfos)
                    {
                        var adaef = goodsAdjustPrice;
                        //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                        var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == goodsAdjustPrice.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                            .Select(s => new
                            {
                                s.Key.goodsID,
                                s.Key.warehouseID,
                                saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                            }).ToList();
                        //获取当天的销售
                        var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.warehouseID == item.warehouseId)?.saleQuantity;
                        //去掉当天销售的历史库存
                        var hisGoodsNum = warehouseGoodsData?.FirstOrDefault(x => x.goodsID == goodsAdjustPrice.Id && x.warehouseID == item.warehouseId)?.goodsNum;

                        goodsAdjustPrice.qualityTime = Convert.ToInt32(hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity));
                        var resultPrice = goodsAdjustPricesData.FirstOrDefault(x => x.receiptNo == item.receiptNo && x.goodsID == goodsAdjustPrice.Id).newPrice;
                        goodsAdjustPrice.price = (decimal)resultPrice;
                    }
                }
                else if (item.receiptNo.Substring(0, 2) == "QT")
                {
                    //其他单
                    var otherBillsGoodsInfos = otherBillsData.Where(x => x.receiptNo == item.receiptNo).ToList().Select(x => x.GoodsInfo)?.ToArray();
                    if (otherBillsGoodsInfos != null && otherBillsGoodsInfos.Length > 0)
                        item.GoodsInfos = otherBillsGoodsInfos;
                    foreach (var goods in item.GoodsInfos)
                    {
                        goods.qualityTime = Convert.ToInt32(otherBillsData.FirstOrDefault(x => x.receiptNo == item.receiptNo && x.goodsID == goods.Id).Num);
                        var price = warehouseGoodsData.Where(x => x.goodsID == goods.Id).FirstOrDefault()?.price;
                        var resultPrice = (price == null || price == 0) ? 0 : price;
                        goods.price = (decimal)resultPrice;
                    }
                }
            }

            return objRet.ToArray();
        }
        #endregion

        #region 更新打印状态
        /// <summary>
        /// 更新打印状态
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<(string, string)> UpdatePrintTagByReceiptNo(ReceiptNoDto data)
        {
            try
            {
                var db = await _printTaskRepository.GetDbContextAsync();
                var printTask = await db.Set<PrintTaskEntity>().AsNoTracking().FirstOrDefaultAsync(x => x.receiptNo == data.receiptNo && x.printTag == 0);
                if (printTask != null)
                {
                    printTask.printTag = 1;
                    _entityHelper.SetUpdationInfo(printTask);
                    await _printTaskRepository.UpdateAsync(printTask, autoSave: true);

                    return ("更新成功", null);
                }
                else
                {
                    return (null, "没有要更新的记录");
                }
            }
            catch(Exception e)
            {
                return (null, e.Message);
            }
        }
        #endregion

        #endregion
    }
    #endregion
}
